% !Mode:: "TeX:UTF-8"

\chapter{饿了么商家管理}

本项目为《软件工程综合实践》的创新项目，实现商家管理功能，具体包括商家的注册和登录、食品管理、食品评论查看、订单查看等多个功能。

\section{需求分析}
\subsection{简介}
商家管理，主要是实现了增加新的商家的功能。并且商家能够添加、修改和删除菜品，同时可以看见用户对菜品的评论和相关的历史订单。除此之外，还要
做好用户和商家的区分以及商家与用户之间的交互。
\subsection{功能性需求}
\begin{enumerate}[label={(\arabic*)}]
    \item 商家注册和登录：商家注册和登录要与用户注册和登录分离，避免既是商家又是用户导致的刷单行为；
    \item 食品管理：商家可以对自己的菜品进行管理，包括修改菜品价格、图片，新增菜品、删除菜品等；
    \item 评论查看：用户对商家菜品的评论需要同步反馈给商家； 
    \item 订单管理：商家需要看到自己的历史订单，包括用户的下单详情、下单时间等。
\end{enumerate}


\section{约束}
本项目因为是课程教学项目，所以对编程语言、平台和工具都有一定的要求，所以
本项目应该有以下约束：

\subsection{系统架构和工具}
\begin{itemize}
    \item 编程语言: JAVA，HTML，Vue3
    \item 数据库：MySQL
    \item 使用SpringBoot框架
\end{itemize}


\subsection{接口}
\subsubsection{Business}
\begin{enumerate}[label={(\arabic*)}]
    \item /businesses/order-types/{orderTypeId}:
    \begin{itemize}
        \item 参数: orderTypeId（订单类型ID，类型为String）。
        \item 返回值：返回一个List<Business>，包含所有与给定订单类型ID相关的商家。
        \item 功能：根据订单类型ID查询相关的商家列表。
    \end{itemize}
    \item /businesses/{businessId}:
    \begin{itemize}
        \item 参数：businessId（商家ID，类型为String）。
        \item 返回值：返回一个Business对象，包含与给定商家ID相关的商家信息。
        \item 功能：根据商家ID查询商家的详细信息。      
    \end{itemize}
    \item /businesses/search:
    \begin{itemize}
        \item 参数：business（商家对象，包含商家ID和加密密码等信息）。
        \item 返回值：返回一个List<Business>，包含所有与搜索关键词相关的商家。
        \item 功能：根据搜索关键词查询相关的商家列表。     
    \end{itemize}
    \item /businesses /authenticate
    \begin{itemize}
        \item 参数：words（搜索关键词，类型为String）。
        \item 返回值：返回一个Business对象，包含商家信息。
        \item 功能：使用商家的加密密码进行身份验证，并返回商家的详细信息。   
    \end{itemize}
    \item /businesses /{businessPassId}
    \begin{itemize}
        \item 参数：businessPassId（商家密码ID，类型为String）。
        \item 返回值：返回一个String，包含商家的公钥。
        \item 功能：检验商家注册情况，并生成且返回商家的公钥。         
    \end{itemize}

    \item /businesses 
    \begin{itemize}
        \item 参数：business（商家对象，包含商家的详细信息和加密密码）。
        \item 返回值：返回一个int，表示保存操作的结果（成功或失败）。
        \item 功能：保存一个新的商家信息到系统中。        
    \end{itemize}

    \item /businesses /key/{businessPassId}
    \begin{itemize}
        \item 参数：businessPassId（商家密码ID，类型为String）。
        \item 返回值：返回一个String，包含商家的公钥。
        \item 功能：根据商家密码ID查询商家的公钥。   
    \end{itemize}

    \item /businesses /{businessPassId}
    \begin{itemize}
        \item 参数：business（商家对象，包含商家的详细信息和可能的加密密码）。
        \item 返回值：返回一个int，表示更新操作的结果（成功或失败）。
        \item 功能：更新指定商家的信息。   
    \end{itemize}
    
    \item /businesses /all/{businessPassId}
    \begin{itemize}
        \item 参数：businessPassId（商家密码ID，类型为String）。
        \item 返回值：返回一个Business对象，包含商家的完整信息。
        \item 功能：根据商家密码ID查询商家的完整信息。     
    \end{itemize}
\end{enumerate}

\subsubsection{foods}
\begin{enumerate}[label={(\arabic*)}]
    \item 	/foods /{foodId}:
    \begin{itemize}
        \item 参数：foodId（食品ID，类型为String）。
        \item 返回值：返回一个int，表示删除操作的结果（通常是删除的记录数）。
        \item 功能：根据食品ID删除指定的食品。  
    \end{itemize}
    \item /foods:
    \begin{itemize}
        \item 参数：food（食品对象，包含食品的详细信息）。
        \item 返回值：返回一个int，表示保存操作的结果（通常是保存的记录数）。
        \item 功能：保存一个新的食品信息到商家系统中。
    \end{itemize}
    \item /foods /{foodId}:
    \begin{itemize}
        \item 参数：foodId（食品ID，类型为String）和food（食品对象，包含更新后的详细信息）。
        \item 返回值：返回一个int，表示更新操作的结果（通常是更新的记录数）。
        \item 功能：根据食品ID更新指定的食品信息。  
    \end{itemize}
\end{enumerate}

\section{软件设计}
\subsection{数据库设计} \label{section:pr4_shujukusheji}
在这个项目中数据库主要涉及两个方面，首先商家列表中添加一些必须的新元素从而可以实现商家的
增添的功能，其次由于项目要求考虑商家对食品的管理
所以我们新建一个食品表用来记录每一个商家的对应食品。
\newline
在uesr表中我们只需要添加一个属性totalPoints用来记录当前用户的积分即可。
\begin{itemize}
    \item[$\bullet$] PK: 主键约束(primary key)
    \item[$\bullet$] FK: 外键约束(foreign key)
    \item[$\bullet$] NN: 非空约束(not null)
    \item[$\bullet$] UQ: 唯一约束(unique)
    \item[$\bullet$] AI: 自增约束(auto increment)
\end{itemize}

\begin{table}[htbp]
    \caption{商家表(business)结构}
    \centering
    \begin{tabular}{|c|c|c|c|c|c|}
    \hline
    No & 字段名         & 数据类型       & size  & 约束       & 说明     \\ \hline
    1  & businessId      & Integer        & 11      & PK、AI、NN & 商家的唯一标识符   \\ \hline
    2  & businessName       & varchar        & 40    & NN       & 商家的名称   \\ \hline
    3  & businessAddress        & varchar        & 50      & NN       & 商家的地址   \\ \hline
    4  & businessExplain        & varchar         & 40       &        & 商家的描述信息   \\ \hline
    5  & businessImg        & Integer        &       &        & 商家的图片链接   \\ \hline
    6  & orderTypeId        & Integer        &       &        & 订单类型的标识符，用于区分不同的订单类型   \\ \hline
    7  & starPrice       & DECIMAL       &       &       & 起送价，顾客下单需要满足的最低金额   \\ \hline
    8  & deliveryPrice        & DECIMAL        &       &        & 配送费   \\ \hline
    9  & remarks       & varchar          &       &        & 商家的备注信息   \\ \hline
    10 & privateKey        & text           &       &        & 商家的私钥，用于加密解密数据   \\ \hline
    11 & publicKey       & text          &       &        & 商家的公钥，用于加密解密数据   \\ \hline
    12 & password        & text        &       &        & 商家的密码   \\ \hline 
    13 & businessPassId       & varchar          &       & NN       & 商家的通行证ID，用于登录验证   \\ \hline
    14 & token        & Integer        &       &        & 商家的令牌，用于身份验证   \\ \hline
\end{tabular}
\end{table}

我们在数据库中新设置了四个元素，起作用具体说明如下：
\begin{enumerate}[label={(\arabic*)}]
    \item businessPassId：商家的通行证ID，用于登录验证。 
    \item password：商家的密码。
    \item privateKey：商家的私钥，用于加密解密数据。
    \item publicKey：商家的公钥，用于加密解密数据。
\end{enumerate}


\subsection{商家管理系统后端设计}
\subsubsection{概述}
商家管理系统旨在为商家提供一个平台，
使其能够管理自己的业务信息、商品信息等。系统采用Spring Boot框架进行设计，并通过RESTful API与前端进行交互。

\subsubsection{系统架构}
系统架构分为五层：Controller层、Service层、Mapper层、PO层和数据库层。
\subsubsection{详细设计}
PO层定义了与数据库表对应的Java对象，包括商家（Business）、商品（Food）等实体。

商家实体（Business）

- **属性**：

  - `businessId`：商家的唯一标识符。
 
  - `businessName`：商家的名称。
 
  - `businessAddress`：商家的地址。
 
  - `businessExplain`：商家的描述信息。
 
  - `businessImg`：商家的图片链接。
 
  - `orderTypeId`：订单类型的标识符，用于区分不同的订单类型。
 
  - `starPrice`：起送价，顾客下单需要满足的最低金额。
 
  - `deliveryPrice`：配送费。
 
  - `remarks`：商家的备注信息。
 
  - `privateKey`：商家的私钥，用于加密解密数据。
 
  - `publicKey`：商家的公钥，用于加密解密数据。
 
  - `password`：商家的密码。
 
  - `businessPassId`：商家的通行证ID，用于登录验证。
 
  - `token`：商家的令牌，用于身份验证。

  - **方法**：包括每个属性的getter和setter方法。
\begin{lstlisting}[ language=xml]
package com.neusoft.elmboot.po;

import java.math.BigDecimal;

public class Business {
    private Integer businessId;
    private String businessName;
    private String businessAddress;
    private String businessExplain;
    private String businessImg;
    private Integer orderTypeId;
    private BigDecimal starPrice;
    private BigDecimal deliveryPrice;
    private String remarks;
    private String privateKey;
    private String publicKey;
    private String password;
    private String businessPassId;
    private String token;

    // Getters and Setters
}
\end{lstlisting}

商品实体（Food）

- **属性**：
 
- `foodId`：商品的唯一标识符。

- `foodName`：商品的名称。

- `foodExplain`：商品的描述信息。

- `foodImg`：商品的图片链接。

- `foodPrice`：商品的价格。

- `businessId`：所属商家的标识符。

- `remarks`：商品的备注信息。

- **方法**：包括每个属性的getter和setter方法。

\begin{lstlisting}[ language=xml]
package com.neusoft.elmboot.po;

import java.math.BigDecimal;

public class Food {
    private Integer foodId;
    private String foodName;
    private String foodExplain;
    private String foodImg;
    private BigDecimal foodPrice;
    private Integer businessId;
    private String remarks;

    // Getters and Setters
}

    \end{lstlisting}
    
\subsubsection{Mapper层设计}

Mapper层使用MyBatis技术与数据库进行交互，定义了与数据库操作相关的接口和SQL语句。

商家Mapper（BusinessMapper）

- **方法**：
 
- `getBusinessById`：根据商家ID查询商家信息。

- `saveBusiness`：保存商家信息到数据库。

- `updateBusiness`：更新数据库中的商家信息。

- `getBusinessByIdByPass`：根据商家通行证ID和密码进行登录操作。

- `getBusinessByPassId`：根据商家通行证ID查询商家是否存在。

- `saveKey`：保存商家的公钥和私钥。

- `getPrivateKey`：根据商家通行证ID获取商家的私钥。

- `getPublicKey`：根据商家通行证ID获取商家的公钥。

- `getEntireBusinessById`：根据商家passId获取商家的全部信息。


\begin{lstlisting}[ language=xml]
    @Mapper
    public interface BusinessMapper {
        
        @Select("select * from business where businessId=#{businessId}")
        public Business getBusinessById(Integer businessId);
        
        public List<Business> listBusinessByWords(List<String> list);
        
        @Select("select * from business where businessPassId=#{businessPassId} and password=#{password}")
        public Business getBusinessByIdByPass(Business business);
        
        @Select("select count(*) from business where businessPassId=#{businessPassId}")
        public int getBusinessByPassId(String businessPassId);
        
        @Update("update  business set businessName = #{businessName}, businessAddress = #{businessAddress},businessExplain = #{businessExplain},businessImg = #{businessImg},orderTypeId = #{orderTypeId}, starPrice = #{starPrice},deliveryPrice = #{deliveryPrice}, password = #{password} where businessPassId=#{businessPassId}")
        public int saveBusiness(Business business);
        
        
        //往数据库存储私钥，返回标志
        @Insert("insert into business values(null,'0','0','0','0',0,0,0,'0',#{businessPassId},'0',#{privateKey},#{publicKey})")
        public int saveKey(Business business);
        
        //从数据库取私钥，返回私钥
        @Select("select privateKey from business where businessPassId=#{businessPassId}")
        public String getPrivateKey(String businessPassId);
    
            
        //从数据库取公钥，返回公钥
        @Select("select publicKey from business where businessPassId=#{businessPassId}")
        public String getPublicKey(String businessPassId);
        
        public int updateBusiness(Business business);
        
        @Select("select * from business where businessPassId=#{businessPassId}")
        public Business getEntireBusinessById(String businessPassId);
        
    }    
\end{lstlisting}

商品Mapper（FoodMapper）

- **方法**：
  
- `listFoodByBusinessId`：根据商家ID查询商品列表。

- `removeFoodByBusinessId`：根据商品ID删除商品。

- `saveFood`：保存商品信息到数据库。

- `updateFood`：更新数据库中的商品信息。
\begin{lstlisting}[ language=xml]
    @Mapper
    public interface FoodMapper {
    
        @Select("select * from food where businessId=#{businessId} order by foodId")
        public List<Food> listFoodByBusinessId(Integer businessId);
        
        @Select("select * from food where foodId=#{foodId}")
        public Food getFoodById(Integer foodId);
        
        @Delete("delete from food where foodId=#{foodId}")
    public int removeFoodByBusinessId(Integer foodId);
    
    @Insert("insert into food values(null,#{foodName},#{foodExplain},#{foodImg},#{foodPrice},#{businessId},null)")
        public int saveFood(Food food);
    
        public int updateFood(Food food);
    }      
\end{lstlisting}
\subsubsection{Service层设计}
Service层作为业务逻辑层，处理具体的业务逻辑，并调用Mapper层的方法。

商家Service（BusinessService）

- **方法**：
 
- `getBusinessById`：调用`BusinessMapper`的方法，返回指定ID的商家信息。

- `saveBusiness`：调用`BusinessMapper`的方法，保存商家信息。

- `updateBusiness`：调用`BusinessMapper`的方法，更新商家信息。

- `getBusinessByIdByPass`：调用`BusinessMapper`的方法，根据通行证ID和密码验证商家信息。

- `getBusinessByPassId`：调用`BusinessMapper`的方法，根据通行证ID检查商家是否存在。

- `saveKey`：调用`BusinessMapper`的方法，保存商家的公钥和私钥。

- `getPrivateKey`：调用`BusinessMapper`的方法，获取商家的私钥。

- `getPublicKey`：调用`BusinessMapper`的方法，获取商家的公钥。

- `getEntireBusinessById`：调用`BusinessMapper`的方法，获取商家的全部信息。

\begin{lstlisting}[ language=xml]
    @Service
    public class BusinessServiceImpl implements BusinessService{
        String key  = "woniucsdnvip8888";
        
        @Autowired
        private BusinessMapper businessMapper;
    
        @Override
        public Business getBusinessById(Integer businessId) {
            return businessMapper.getBusinessById(businessId);
        }
        
        @Override
        public List<Business> listBusinessByWords(String words){
            List<Term> terms  = StandardTokenizer.segment(words);
            List<String> wordList = new ArrayList<>();
            for (Term term : terms) {
                wordList.add(term.word); // 将每个 Term 对象的 word 属性添加到列表中
            }
            return businessMapper.listBusinessByWords(wordList);
        }
        
        
        @Override
        public Business getBusinessByIdByPass(Business business) {
            Business b=businessMapper.getBusinessByIdByPass(business);
            if(b!=null) {
                String token = TokenUtils.getToken(b.getBusinessPassId().toString(), b.getPassword(),"business");
                token=AESUtils.encrypt(token, key);
                b.setToken(token);
                b.setPrivateKey("");
            }
            return b;
        }
        
        @Override
        public int getBusinessByPassId(String businessPassId) {
            return businessMapper.getBusinessByPassId(businessPassId);
        }
        
        @Override
        public int saveBusiness(Business business) {
            return businessMapper.saveBusiness(business);
        }
        
        
        @Override
        public int saveKey(Business business){
            int flag=businessMapper.saveKey(business);
            return flag;
        }
        
        @Override
        public String getPrivateKey(String businessPassId) {
            return businessMapper.getPrivateKey(businessPassId);
        }
        
        @Override
        public String getPublicKey(String businessPassId) {
            return businessMapper.getPublicKey(businessPassId);
        }
        
        @Override
        public int updateBusiness(Business business) {
            return businessMapper.updateBusiness(business);
        }
        
        @Override
        public Business getEntireBusinessById(String businessPassId) {
            Business b=businessMapper.getEntireBusinessById(businessPassId);
            if(b!=null) {
                b.setPrivateKey("");
            }
            return  b;
        }   
    }
        
\end{lstlisting}

商品Service（FoodService）

- **方法**：

- `listFoodByBusinessId`：调用`FoodMapper`的方法，返回商品列表。

- `removeFoodByBusinessId`：调用`FoodMapper`的方法，删除商品。

- `saveFood`：调用`FoodMapper`的方法，保存商品信息。

- `updateFood`：调用`FoodMapper`的方法，更新商品信息。
\begin{lstlisting}[ language=xml]
    @Service
    public class FoodServiceImpl implements FoodService{
        
        @Autowired
        private FoodMapper foodMapper;
    
        @Override
        public List<Food> listFoodByBusinessId(Integer businessId) {
            return foodMapper.listFoodByBusinessId(businessId);
        }
        
        @Override
        public int removeFoodByBusinessId(Integer foodId) {
            return foodMapper.removeFoodByBusinessId(foodId);
        }
        
        @Override
        public int saveFood(Food food) {
            return foodMapper.saveFood(food);
        }
    
        @Override
        public int updateFood(Food food) {
            return foodMapper.updateFood(food);
        }
    
    }    
\end{lstlisting}   
\subsubsection{Controller层设计}
Controller层处理来自客户端的请求，并调用Service层的方法。

商家Controller（BusinessController）

- **方法**：
  
- `getBusinessById`：处理GET请求，根据商家ID返回商家信息。

- `saveBusiness`：处理POST请求，保存新的商家信息。

- `updateBusiness`：处理PUT请求，更新商家信息。

- `getBusinessByIdByPass`：处理POST请求，通过通行证ID和密码验证商家信息。

- `getBusinessByPassId`：处理POST请求，根据通行证ID获取商家的公钥。

- `getPublicKey`：处理GET请求，根据商家通行证ID返回商家的公钥。

- `getEntireBusinessById`：处理GET请求，获取商家的全部信息。

\begin{lstlisting}[ language=xml]
    @RestController
    @RequestMapping("/businesses")
    public class BusinessController {
        
        RSAUtils rsaUtils=new  RSAUtils();
        
        @Autowired
        private BusinessService businessService;
        
        @GetMapping("/{businessId}")
        public Business getBusinessById(Business business) throws Exception{
            return businessService.getBusinessById(business.getBusinessId());
        }
        
        @GetMapping("/search")
        public List<Business> listBusinessByWords(String words)throws Exception{
            return businessService.listBusinessByWords(words);
        }
        
        @PostMapping("/authenticate")
        public Business getBusinessByIdByPass(Business business) throws Exception{
            // 使用私钥解密用户密码
            String privateKeyBase64=businessService.getPrivateKey( business.getBusinessPassId());
            RSA rsa = new RSA(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue(), privateKeyBase64, null);  // 放入私钥来生成对象
            String password=rsa.decryptStr(business.getPassword(), KeyType.PrivateKey);
            String hashedPassword=DigestUtils.md5DigestAsHex((password +  business.getBusinessPassId()).getBytes());//md5加密，手机号为盐
            hashedPassword=DigestUtils.md5DigestAsHex((hashedPassword +  business.getBusinessPassId()).getBytes());//二次加密
            hashedPassword=DigestUtils.md5DigestAsHex((hashedPassword +  business.getBusinessPassId()).getBytes());//三次加密
            business.setPassword(hashedPassword);  
            // 返回找到的用户对象
            return businessService.getBusinessByIdByPass(business);
        }
        
        
        @PostMapping("/{businessPassId}")
        public String getBusinessByPassId(Business business) throws Exception{
            int flag=businessService.getBusinessByPassId(business.getBusinessPassId());
            //判断用户是否存在
            if(flag==0) {
                //返回公钥
                String[]keysBase64=rsaUtils.rsa_jiami(business);
                business.setPublicKey(keysBase64[0]);
                business.setPrivateKey(keysBase64[1]);
                businessService.saveKey(business);
                return keysBase64[0]; 
            }
            else return "1";
        }
        
        @PostMapping("")
        public int saveBusiness(Business business) throws Exception{
            String privateKeyBase64=businessService.getPrivateKey(business.getBusinessPassId());
            RSA rsa = new RSA(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue(), privateKeyBase64, null);  // 放入私钥来生成对象
            String password=rsa.decryptStr(business.getPassword(), KeyType.PrivateKey);//明文密码
            String hashedPassword=DigestUtils.md5DigestAsHex((password + business.getBusinessPassId()).getBytes());//md5加密，手机号为盐
            hashedPassword=DigestUtils.md5DigestAsHex((hashedPassword + business.getBusinessPassId()).getBytes());//二次加密
            hashedPassword=DigestUtils.md5DigestAsHex((hashedPassword + business.getBusinessPassId()).getBytes());//三次加密
            business.setPassword(hashedPassword); 
            return businessService.saveBusiness(business);
        }
        
    
        @GetMapping("/key/{businessPassId}")
        public String getPublicteKey(Business business) throws Exception{
            return businessService.getPublicKey(business.getBusinessPassId());
        }
        
        @PutMapping("/{businessPassId}")
        public int updateBusiness(Business business) throws Exception{
            //String password=business.getPassword();
            if(business.getPassword()==null||business.getPassword()=="") {}
            else{
                String password=rsaUtils.rsa_endjiemi(businessService.getPrivateKey(business.getBusinessPassId()),business.getPassword());
                business.setPassword(rsaUtils.md5jiami(password,business.getBusinessPassId())); 
            }
            return businessService.updateBusiness(business);
        } 
        
        
        @GetMapping("/all/{businessPassId}")
        public Business getEntireBusinessById(Business business) {
            return businessService.getEntireBusinessById(business.getBusinessPassId());
        }
    }
\end{lstlisting}

商品Controller（FoodController）

- **方法**：
 
- `listFoodByBusinessId`：处理GET请求，根据商家ID返回商品列表。

- `removeFoodByBusinessId`：处理DELETE请求，删除商品。

- `saveFood`：处理POST请求，保存新的商品信息。

- `updateFood`：处理PUT请求，更新商品信息。

\begin{lstlisting}[ language=xml]
    @RestController
@RequestMapping("/foods")
public class FoodController {
    
    @Autowired
    private FoodService foodService;

    @GetMapping("/businesses/{businessId}")
    public List<Food> listFoodByBusinessId(Food food) throws Exception{
        return foodService.listFoodByBusinessId(food.getBusinessId());
    }
    
    @DeleteMapping("/{foodId}")
    public int removeFoodByBusinessId(Food food) throws Exception{
        return foodService.removeFoodByBusinessId(food.getFoodId());
    } 
    
    @PostMapping("")
    public int saveFood(Food food) throws Exception {
        return foodService.saveFood(food);
    }
    

    @PutMapping("/{foodId}")
    public int updateFood(Food food) throws Exception{
        return foodService.updateFood(food);
    }
}
\end{lstlisting}
\subsection{前端设计}
\subsubsection{商家功能整体设计}
在先前的登录界面新增商家登录选项并且设置路由。同时在Footer中设计导航逻辑，使得“我的”页面，可以在商家登录和用户登录显示不同的界面，实现不同的功能。
\begin{lstlisting}[ language=xml]
    toMy() {
            const user = this.$getSessionStorage('user');
            const businesser = this.$getSessionStorage('businesser');

             if (user) {
             // 如果用户登录信息存在，则导航到用户页面
              this.$router.push({ path: '/my' });
            } else if (businesser) {
               // 如果商家登录信息存在，则导航到商家页面
                this.$router.push({ path: '/mybusiness' });
                } else {
                 // 如果没有角色信息，则导航到登录页面
                 this.$router.push({ path: '/login' });
                   }
                }
\end{lstlisting}

\subsubsection{商家登录和注册}
在用户登录界面新增商家登录选项，点击可以跳转到商家登录界面，进行商家登录或者注册。与用户登录类似，
但是登录或者注册成功会进入商家的对应系统。
\begin{figure}[thbp]
        \centering
        \includegraphics[width=0.3\textwidth]{point_1}
        \caption{商家添加菜品}\label{fig:point_1}
        \vspace{\baselineskip}
        \end{figure}

    \begin{figure}[thbp]
            \centering
            \includegraphics[width=0.3\textwidth]{point_2}
            \caption{商家页面展示}\label{fig:point_2}
            \vspace{\baselineskip}
            \end{figure}

\subsubsection{菜品管理}
商家根据businessId查询所属食品信息，发送POST请求，添加或者删除新食品，将服务器返回的新的食品数据添加到foodArr数组中，
清空表单并关闭添加食品的表单，刷新页面进行显示。

\subsubsection{评论查看}

用户对菜品的评论可以同步出现在商家的菜品下面，商家同步可以看到评论。

\subsubsection{订单管理}
点击订单页面商家可以看到已完成的订单的支付时间、订单的详细收入、用户对订单的评价等内容。
\begin{figure}[thbp]
        \centering
        \includegraphics[width=0.3\textwidth]{point_3}
        \caption{商家订单页面展示}\label{fig:point_3}
        \vspace{\baselineskip}
        \end{figure}
